/**
  * @brief  Define Peripheral Function
  * @note
  * @param  name, peripheral name
  *         *inst_info, instruction information
  * @retval MemoryMap_t*
  */

#define TIMER_REG_CR            0x00
#define TIMER_REG_SR            0x04
#define TIMER_REG_PSC           0x08
#define TIMER_REG_LOAD          0x0c
#define TIMER_REG_COUNT         0x10

int _timer(const char *name, InstInfo_t *inst_info)
{
    MemoryMap_t *pm = _find_by_name(name);

    if ( !pm ) {
        return 0;
    }

    static uint32_t _timeup = 0;

    if ( BIT(pm->memory->buf[TIMER_REG_CR/4], 0) ) // [0]: enbale
    {
        _timeup ++;

        if ( 0 == pm->memory->buf[TIMER_REG_COUNT/4] ) {
            pm->memory->buf[TIMER_REG_COUNT/4] = pm->memory->buf[TIMER_REG_LOAD/4];
        }

        if ( _timeup > pm->memory->buf[TIMER_REG_PSC/4] )
        {
            _timeup = 0;

            pm->memory->buf[TIMER_REG_COUNT/4] --;
            if ( 0 == pm->memory->buf[TIMER_REG_COUNT/4] ) {
                _s_irq |= INT_IRQ_TIMER1;
            }
        }
    } else {
        _timeup = 0;
        pm->memory->buf[TIMER_REG_COUNT/4] = 0;
    }

    if ( DATA_MASK(inst_info->mem_addr, 4, 28) != DATA_MASK(pm->address, 4, 28) ) {
        return 0;
    }

    if ( inst_info->mem_we )
    {
        switch ( DATA_MASK(inst_info->mem_addr, 8, 0) )
        {
            case TIMER_REG_SR : {
                pm->memory->buf[TIMER_REG_SR/4] &= ~SHIFT_L(BIT(inst_info->mem_data, 0), 0); // [0]: timing-up flag
                break;
            }
        }
    }

    return 0;
}
